﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PCR.Logic
{
    using PCR.Base;
    
    /// <summary>
    /// Patient virus type and value definition, 
    /// a patient may contains several viruses
    /// </summary>
    internal class PatientVirus : IPatientVirus
    {
        /// <summary>
        /// Virus type object ID, becase the IVirusType name and value may changed
        /// we just store a link here, you need to find the real value when you want
        /// to use it
        /// </summary>
        public Guid VirusTypeID
        {
            get { return this._virusTypeID; }
            set { this._virusTypeID = value; }
        }
        Guid _virusTypeID;

        /// <summary>
        /// Get or set the current virus CT
        /// </summary>
        public double VirusCTVal 
        {
            get { return this._ctVal; }
            
            set 
            {
                System.Diagnostics.Debug.Assert(
                    value >= PCRRoot.Instance.ConfigManager.MinCTVal &&
                    value <= PCRRoot.Instance.ConfigManager.MaxCTVal);
                
                this._ctVal = value; 
            }
        }
        double _ctVal = 0.0;

        /// <summary>
        /// Get or set the reference Cell CT
        /// </summary>
        public double ReferCellCTVal 
        {
            get { return this._referCellVal; }
            
            set 
            {
                System.Diagnostics.Debug.Assert(
                    value >= PCRRoot.Instance.ConfigManager.MinCTVal &&
                    value <= PCRRoot.Instance.ConfigManager.MaxCTVal);
                        
                this._referCellVal = value; 
            }
        }
        double _referCellVal = 0.0;

        /// <summary>
        /// Get the revised CT
        /// </summary>
        public double RevisedCT
        {
            get 
            {
                // First get the active curve parameter
                IStdCurve activeCurve = PCRRoot.Instance.StdCurveManager.Active;
                if (activeCurve == null)
                    return 0.0;

                // Get the curve param
                IStdCurveParam curveParam = activeCurve.CurveParam;
                if (curveParam == null)
                    return 0.0;

                // Get the virus type from the VirusTypeID
                IVirusType virusType = PCRRoot.Instance.VirusTypeManager.GetByID(VirusTypeID);
                if (curveParam == null)
                    return 0.0;

                double virusedCT = 0.0;
                if (!PCRRoot.Instance.Calculator.GetVirusRevisedCT(
                        this, curveParam, virusType, out virusedCT))
                {
                    // Log error here
                    return 0.0;
                }

                // Modify for new requirement
                if (virusedCT > PCRRoot.Instance.ConfigManager.MaxCTVal)
                {
                    virusedCT = PCRRoot.Instance.ConfigManager.MaxCTVal;
                }

                return virusedCT;
            }
        }

        /// <summary>
        /// Get virus exponent
        /// calculated by active standard curve, virus parameter and 
        /// current CT value
        /// return -1 if calculate failed
        /// return 0, mean "阴性"， all exponent < VirusSafetyExponent will set to 0
        /// </summary>
        public double Exponent
        {
            // Calculate the virus exponent internally from local data
            get 
            {
                // First get the active curve parameter
                IStdCurve activeCurve = PCRRoot.Instance.StdCurveManager.Active;
                if (activeCurve == null)
                        return -1;
                
                // Get the curve param
                IStdCurveParam curveParam = activeCurve.CurveParam;
                if (curveParam == null)
                    return -1;

                // Get the virus type from the VirusTypeID
                IVirusType virusType = PCRRoot.Instance.VirusTypeManager.GetByID(VirusTypeID);
                if (curveParam == null)
                    return -1;

                double exponent = -1;
                if (!PCRRoot.Instance.Calculator.GetVirusExponent(
                        this, curveParam, virusType, out exponent))
                {
                    // Log error here
                    return -1;
                }

                // Set to 0 if < VirusSafetyExponent
                //if (exponent < PCRRoot.Instance.VirusTypeManager.VirusSafetyExponent*PCRRoot.Instance.VirusTypeManager.BaseCellCount)
                {
                    //exponent = 0;

                    // For the new requirement
                    //exponent = PCRRoot.Instance.VirusTypeManager.VirusSafetyExponent * PCRRoot.Instance.VirusTypeManager.BaseCellCount;
                }

                // Set to 1 digital
                return Math.Round(exponent, 1);
            }
        }
    }
}
